package spring;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.annotation.PostConstruct;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import spring.bean.User;
import spring.bean.post.MyBeanPostProcessor;
import spring.condition.LinuxCondition;
import spring.condition.WindowsCondition;

import javax.sql.DataSource;

@Configuration
@ComponentScan()
@PropertySource("classpath:/address.properties")
@PropertySource("classpath:/jdbc.properties")
@PropertySource("classpath:/hsql.properties")
@MapperScan("spring.mapper")
@EnableAspectJAutoProxy
@EnableTransactionManagement
//@Import(MyBeanPostProcessor.class)
public class AppConfig {

    @Value("${hsql.url}")
    String hsqlUrl;

    @Value("${hsql.username}")
    String hsqlUsername;

    @Value("${hsql.password}")
    String hsqlPassword;

    @Bean("bill")
    @Conditional({WindowsCondition.class})
    public User user01() {
        return new User("Bill", 18);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public User user02() {
        return new User("Linus", 18);
    }

    @Bean(name = {"dataSourceTest"})
    @Profile({"default", "test"})
    DataSource dataSourceTest() {
        return getDataSource();
    }

    @Bean(name = {"dataSourceDev"})
    @Profile("dev")
    DataSource dataSourceDev() {
        return getDataSource();
    }

    @Bean(name = {"dataSourceProd"})
    @Profile("prod")
    DataSource dataSourceProd() {
        return getDataSource();
    }

    private DataSource getDataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(hsqlUrl);
        config.setUsername(hsqlUsername);
        config.setPassword(hsqlPassword);
        config.addDataSourceProperty("autoCommit", "true");
        config.addDataSourceProperty("connectionTimeout", "5");
        config.addDataSourceProperty("idleTimeout", "60");
        return new HikariDataSource(config);
    }

    @Bean
    JdbcTemplate createJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    SqlSessionFactoryBean createSqlSessionFactoryBean(DataSource dataSource) {
        var bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean;
    }

    @Bean
    PlatformTransactionManager createTxManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @PostConstruct
    @Autowired
    void initDatabase(JdbcTemplate jdbcTemplate) {
        System.out.println("initDatabase");
        jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS users (" +
                "id BIGINT IDENTITY NOT NULL PRIMARY KEY, " +
                "email VARCHAR(100) NOT NULL, " +
                "password VARCHAR(100) NOT NULL, " +
                "name VARCHAR(100) NOT NULL, " +
                "UNIQUE (email))");
    }
}
